﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WJP.Diagnostics
{
    /// <summary>
    /// 事件追踪器
    /// </summary>
    public class EventTrace
    {
        private static List<EventTraceListener> Listeners = new List<EventTraceListener>();

        /// <summary>
        /// 添加事件追踪监听器
        /// </summary>
        /// <param name="listener"></param>
        public static void AddListener(EventTraceListener listener)
        {
            Listeners.Add(listener);
        }

        /// <summary>
        /// 移除事件追踪监听器
        /// </summary>
        /// <param name="listener"></param>
        public static void RemoveListener(EventTraceListener listener)
        {
            Listeners.Remove(listener);
        }

        private static void Write(string target, object context, long elapsed)
        {
            foreach(var listener in Listeners)
            {
                listener.Write(target, context, elapsed);
            }
        }

        /// <summary>
        /// 开始追踪事件
        /// </summary>
        /// <param name="target">事件类型</param>
        /// <param name="context">追踪内容</param>
        /// <returns></returns>
        public static IDisposable Start(string target, object context)
        {
            return new EventTraceStopwatch(target, context).Start();
        }

        private class EventTraceStopwatch : IDisposable
        {
            private string Target { get; set; }

            private object Context { get; set; }

            private Stopwatch Stopwatch { get; set; }

            public bool Cancel { get; set; }

            public EventTraceStopwatch(string target, object context)
            {
                Target = target;
                Context = context;
                Stopwatch = new Stopwatch();
            }

            public EventTraceStopwatch Start()
            {
                Stopwatch.Start();
                return this;
            }

            public void Stop()
            {
                try
                {
                    Stopwatch.Stop();
                    if (!Cancel)
                    {
                        Write(Target, Context, Stopwatch.ElapsedTicks);
                    }
                }
                finally
                {

                }
            }

            void IDisposable.Dispose()
            {
                Stop();
            }
        }
    }
}
